package me.hekr.iotos.softgateway.subsystem.service;

import static java.util.stream.Collectors.toList;

import com.fasterxml.jackson.core.type.TypeReference;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.stream.IntStream;
import lombok.extern.slf4j.Slf4j;
import me.hekr.iotos.softgateway.common.utils.JsonUtil;
import me.hekr.iotos.softgateway.core.enums.ErrorCode;
import me.hekr.iotos.softgateway.core.klink.KlinkService;
import me.hekr.iotos.softgateway.core.klink.ModelData;
import me.hekr.iotos.softgateway.network.common.DecodePacket;
import me.hekr.iotos.softgateway.network.common.coder.PacketCoder;
import me.hekr.iotos.softgateway.network.udp.UdpClient;
import me.hekr.iotos.softgateway.network.udp.UdpServer;
import me.hekr.iotos.softgateway.subsystem.dto.RadioDevice;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/** @author iotos */
@Slf4j
@Service
public class UdpServerService {
  private static final int SERVER_PORT = 1030;
  private final PacketCoder<String> packetCoder = getPacketCoder();
  private UdpServer<String> udpServer;
  private UdpClient<String> udpClient;
  @Autowired private KlinkService klinkService;

  private static PacketCoder<String> getPacketCoder() {
    return new PacketCoder<String>() {
      @Override
      public byte[] encode(String s) {
        return s.getBytes(StandardCharsets.UTF_8);
      }

      @Override
      public DecodePacket decode(byte[] bytes) {
        return DecodePacket.wrap(new String(bytes, StandardCharsets.UTF_8), bytes.length);
      }
    };
  }

  public void start() {
    startServer();
    startClient();
  }

  private void startClient() {
    udpClient = new UdpClient<>("localhost", SERVER_PORT, 1021);
    udpClient.setMessageListener(
        ctx -> System.out.println("收到来自 " + ctx.getAddress() + " 的消息：" + ctx.getMessage()));
    udpClient.setPacketCoder(packetCoder);
    udpClient.setEnableNetLog(false);
    udpClient.setSync(true);
    // 同步模式设置超时时间
    udpClient.setTimeout(3000);
    udpClient.start();
  }

  private void startServer() {
    udpServer = new UdpServer<>(1030);
    // 设置编解码
    udpServer.setPacketCoder(packetCoder);

    // 设置消息监听器
    udpServer.setMessageListener(
        ctx -> {
          // 模拟获取设备等信息
          String msg = ctx.getMessage();
          log.info("收到消息：{}", msg);
          // 获取所有设备信息
          switch (msg) {
            case "getAllStatus":
              udpServer.send(ctx, JsonUtil.toJson(getDeviceStatus()));
              break;
              // 可以自行扩展其他指令
            default:
              if (msg.startsWith("setVol")) {
                udpServer.send(ctx, "OK");
              }
          }
        });
    // 开启网络日志
    udpServer.setEnableNetLog(true);
    udpServer.start();
  }

  private List<RadioDevice> getDeviceStatus() {
    return IntStream.range(0, 3)
        .mapToObj(
            i -> {
              RadioDevice d = new RadioDevice();
              d.setRadioDevId("radio_id_" + i);
              d.setStatus(i % 2);
              d.setPlayStat(i % 3);
              d.setVol(i);
              return d;
            })
        .collect(toList());
  }

  public void setVol(String radioDevId, Integer vol) {
    String resp = udpClient.send("setVol:" + radioDevId + ":" + vol);
    RadioDevice d = new RadioDevice(radioDevId);
    if ("OK".equals(resp)) {
      klinkService.devSend(d, ModelData.cmd("report").param("vol", vol));
      klinkService.sendCloudSendResp(d, ErrorCode.SUCCESS);
    } else {
      log.error("控制失败 radioDevId: {}" + radioDevId);
      klinkService.sendCloudSendResp(d, 2000, "unknown");
    }
  }

  public List<RadioDevice> getAllStatus() {
    return JsonUtil.fromJson(
        udpClient.send("getAllStatus"), new TypeReference<List<RadioDevice>>() {});
  }
}
